﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CommonTools.Util
{
    public class TcpFileServerHelper
    {
        string _ip = "127.0.0.1";
        short _port = 29908;
        string _path = string.Empty;
        int blockSize = 1024;
        long fileSize = 0;
        int currentProgress = 0;
        public event Action<int> ProgressRefush;

        public TcpFileServerHelper(string ip, short port, string path)
        {
            _ip = ip;
            _port = port;
            _path = path;
            TcpListener tcpListener = new TcpListener(IPAddress.Parse(_ip), port);
            tcpListener.Start();
            Task.Factory.StartNew(() => ListenerHand(tcpListener));
        }

        private void ListenerHand(TcpListener tcpListener)
        {
            while(true)
            {
                try
                {
                    TcpClient tcpClient = tcpListener.AcceptTcpClient();
                    if (tcpClient.Connected)
                    {
                        NetworkStream stream = tcpClient.GetStream();
                        Task.Factory.StartNew(() => ClientRecvHand(stream));
                        string fileName = Path.GetFileName(_path);
                        List<byte> dataHeads = new List<byte>();

                        byte[] fileNameByte = Encoding.Unicode.GetBytes(fileName);

                        byte fileNameLength = Convert.ToByte(fileNameByte.Length);
                        dataHeads.Add(fileNameLength);
                        dataHeads.AddRange(fileNameByte);
                        FileStream fileStrem = new FileStream(_path, FileMode.Open);
                        int fileReadSize = 0;
                        fileSize = 0;
                        while (fileSize < fileStrem.Length)
                        {
                            List<byte> data = new List<byte>();
                            data.AddRange(dataHeads);
                            long lenth = blockSize - 1 - fileNameLength - 8;
                            lenth = fileStrem.Length - fileSize > lenth ? lenth : fileStrem.Length - fileSize;
                            data.AddRange(BitConverter.GetBytes(lenth));
                            byte[] buffer = new byte[lenth];
                            fileReadSize = fileStrem.Read(buffer, 0, buffer.Length);
                            data.AddRange(buffer);
                            stream.Write(data.ToArray(), 0, data.Count());
                            fileSize += fileReadSize;

                        }
                        fileStrem.Flush();
                        fileStrem.Close();

                    }
                }
                catch (Exception ex)
                {

                }
            }
        }

        private void ClientRecvHand(NetworkStream stream)
        {
            BinaryReader reader = new BinaryReader(stream);
            while (true)
            {
                var data = reader.ReadBytes(8);
                if (data.Length != 8)
                {
                    Thread.Sleep(10);
                    continue;
                }
                long tranfromedLength = Convert.ToInt64(data);
                int tempProgress = (int)(tranfromedLength * 100 / fileSize);
                if (tempProgress != currentProgress)
                {
                    currentProgress = tempProgress;
                    ProgressRefush?.Invoke(currentProgress);
                }
                if (tranfromedLength >= fileSize)
                {
                    break;
                }
            }
                        stream.Flush();
                        stream.Close();
        }
    }
}
